/**
 * 
 */
package org.rollinitiative.d20.entity;

import javax.xml.namespace.QName;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.rollinitiative.d20.AdjustableValue;
import org.rollinitiative.d20.Adjustment;
import org.rollinitiative.d20.Adjustment.AdjustmentSource;

/**
 * The AbilityValue extends the basic AdjustableValue in order to provide event-driven notification
 * to subscribers of changes in the Ability modifier due to current Ability value.
 * 
 * @author bebopjmm
 * 
 */
public class AbilityValue extends AdjustableValue
{
   static final Log LOG = LogFactory.getLog(AbilityValue.class);

   public static final int DEFAULT_VALUE = 10;

   /**
    * Ability Modifer adjustment
    */
   Adjustment abilityMod;

   /**
    * Ability that this AbilityValue is associated with.
    */
   Ability ability;


   /**
    * Initializes an AbilityValue to have the specified baseValue and no subscribers.
    * 
    * @param baseValue base value for the AdjustableValue
    * @param ability Ability that this AbilityValue represents
    */
   public AbilityValue(int baseValue, Ability ability)
   {
      super(baseValue);
      this.ability = ability;
      this.setName(ability.toString());
      abilityMod = new Adjustment(AdjustmentSource.INHERENT,
            Ability.getModifier(this.getCurrent()), new QName(
                  "java:org.rollinitiative.d20.entity", "ability." + ability.name()));
   }


   /**
    * @return the Ability enum that this AbilityValue is associated with.
    */
   public Ability getAbility()
   {
      return ability;
   }


   /**
    * @return The ability modifier adjustment for this ability value.
    */
   public Adjustment getModifier()
   {
      return abilityMod;
   }


   /**
    * Triggers update the ability modifier Adjustment and subscriber notification following
    * baseValue change.
    * 
    * @param baseValue the baseValue to set
    * @since incr-0.1
    */
   @Override
   public synchronized void setBase(int baseValue)
   {
      super.setBase(baseValue);
      updateAdjustment();
   }


   /**
    * This method returns the ability modifier value for the current ability value.
    * 
    * @return current ability modifer value.
    */
   public int getAbilityModifier()
   {
      return abilityMod.getValue();
   }


   @Override
   public synchronized void addAdjustment(Adjustment adjustment)
   {
      LOG.debug("Adding new Adjustment: " + adjustment.getPedigree().getLocalPart());
      super.addAdjustment(adjustment);
      updateAdjustment();
   }


   @Override
   public synchronized void removeAdjustment(Adjustment adjustment)
   {
      LOG.debug("Removing Adjustment: " + adjustment.getPedigree().getLocalPart());
      super.removeAdjustment(adjustment);
      updateAdjustment();

   }


   /*
    * (non-Javadoc)
    * 
    * @see org.rollinitiative.d20.AdjustmentListener#valueChanged(org.rollinitiative.d20.Adjustment)
    */
   @Override
   public void valueChanged(Adjustment adjustment)
   {
      super.valueChanged(adjustment);
      updateAdjustment();
   }


   /**
    * Updates the ability modifier value and notifies all subscribers.
    */
   void updateAdjustment()
   {
      abilityMod.setValue(Ability.getModifier(this.getCurrent()));
      LOG.debug("New abilityMod = " + abilityMod.getValue());
   }

}
